/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-08-08     admin       the first version
 */
#include "sy_queue.h"
#include "stdlib.h"
#include "rtthread.h"

void *my_malloc(size_t size)
{
    return rt_malloc(size);
}
void my_free(void *_void)
{
    rt_free(_void);
}

cQueue cQueue_Create(size_t queu_max_size,size_t data_max_size,cQUEUE_mode mode)
{
    cQueue queue=NULL;
    queue=(cQueue)my_malloc(sizeof(cQUEUE_t));
    if(queue==NULL)
    {
        rt_kprintf("my_malloc cQUEUE_t failed\n");
        return NULL;
    }
    queue->data=my_malloc(queu_max_size*data_max_size);
    if(queue->data==NULL)
    {
        rt_kprintf("my_malloc queue->data failed\n");
        my_free(queue);
        return NULL;
    }
    queue->data_len=(size_t*)my_malloc(sizeof(size_t)*queu_max_size);
    if(queue->data_len==NULL)
    {
        rt_kprintf("my_malloc queue->data_len failed\n");
        my_free(queue->data);
        my_free(queue);
        return NULL;
    }

    queue->push_count=0;
    queue->rec_count=0;
    queue->size=0;
    queue->data_max_size=data_max_size;
    queue->queue_max_size=queu_max_size;
    queue->mode=mode;
    return queue;
}
cQUEUE_sta cQueue_Push(cQueue queue,void *src,size_t size)
{

    if (queue==NULL||src==NULL||size==0)
    {
        return QUEUE_NULL;
    }
    //rt_kprintf("cQueue_Push %p size:%d queue->data_max_size:%d\n",queue,size,queue->data_max_size);
    if(size>queue->data_max_size)
    {
        return QUEUE_MEM_FULL;
    }
    if (queue->size>=queue->queue_max_size&&queue->mode==NO_COVER)
    {
        return QUEUE_MEM_FULL;
    }
    void *t_p=(void*)(queue->data+queue->push_count*queue->data_max_size);
    //printf("%d %d\n",queue->push_count,size);
    rt_memcpy(t_p,src,size);
    queue->data_len[queue->push_count]=size;
    queue->push_count++;
    queue->size++;
    if(queue->push_count>(queue->queue_max_size-1))
    {
        queue->push_count=0;
    }
    if(queue->size>queue->queue_max_size)
    {
        queue->size=queue->queue_max_size;
    }

    return QUEUE_OK;
}
cQUEUE_sta cQueue_Receivelen(cQueue queue)
{
    if(queue==NULL)
    {
        return QUEUE_NULL;
    }
    if(queue->size<=0)
    {
        return (cQUEUE_sta)0;
    }
    size_t len=queue->data_len[queue->rec_count];

    return (cQUEUE_sta)len;
}
#include "rtthread.h"
cQUEUE_sta cQueue_Receive(cQueue queue,void *dest)
{

    if(queue==NULL||dest==NULL)
    {
        return QUEUE_NULL;
    }
    if(queue->size<=0)
    {
        return (cQUEUE_sta)0;
    }
    size_t len=queue->data_len[queue->rec_count];
    void *t_p=queue->data+queue->rec_count*queue->data_max_size;
    rt_memcpy(dest,t_p,len);
    queue->size--;
    queue->rec_count++;
    if(queue->rec_count>(queue->queue_max_size-1))
    {
        queue->rec_count=0;
    }
    return (cQUEUE_sta)len;
}
cQUEUE_sta cQueue_Clean(cQueue queue)
{
    if(queue==NULL)
    {
        return QUEUE_NULL;
    }
    queue->size=0;
    queue->push_count=0;
    queue->rec_count=0;
    return QUEUE_OK;
}
cQUEUE_sta cQueue_Size(cQueue queue)
{
    if(queue==NULL)
    {
        return (cQUEUE_sta)QUEUE_NULL;
    }
    return (cQUEUE_sta)queue->size;
}
/*
cQUEUE_sta cQueue_Showall(cQueue queue)
{
    if(queue==NULL)
    {
        return QUEUE_NULL;
    }
    rt_kprintf("size:%ld\n",queue->size);
    for (size_t i = 0; i < queue->size; i++)
    {
        //rt_kprintf("len:%ld data:%s\n",queue->data_len[queue->rec_count+i],(char*)&queue->data[(queue->rec_count+i)*queue->data_max_size]);
    }
    return QUEUE_OK;
}
*/
cQUEUE_sta cQueue_Free(cQueue *queue)
{
    if(queue==NULL)
    {
        return QUEUE_NULL;
    }
    if(*queue==NULL)
    {
        return QUEUE_NULL;
    }
    rt_kprintf("queue=%p\n",queue);
    if ((*queue)->data!=NULL)
    {
        my_free((*queue)->data);
        (*queue)->data=NULL;
    }
    if((*queue)->data_len==NULL)
    {
        my_free((*queue)->data_len);
        (*queue)->data_len=NULL;
    }
    my_free(*queue);
    *queue=NULL;

    return QUEUE_OK;
}
